﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Web;
using Castle.Core;
using FlexiCommerce.Configuration;
using FlexiCommerce.Engine;
using FlexiCommerce.Installation;
using FlexiCommerce.Plugin;
using FlexiCommerce.Security;

namespace FlexiCommerce.Web
{
    public class RequestLifeCycleHandler : IStartable, IAutoStart
    {

        readonly IErrorHandler errors;
        readonly IWebContext webContext;
        readonly EventBroker broker;
        readonly InstallationManager installer;

        protected bool initialized = false;
        protected bool checkInstallation = false;
        protected string installerUrl = "~/Edit/Install/Begin/Default.aspx";


        public RequestLifeCycleHandler(IWebContext webContext, EventBroker broker, InstallationManager installer, IErrorHandler errors, EngineSection engineConfig)
            : this(webContext, broker, installer, errors)
        {
            checkInstallation = engineConfig.Installer.CheckInstallationStatus;
            installerUrl = engineConfig.Installer.InstallUrl;
        }

        /// <summary>Creates a new instance of the RequestLifeCycleHandler class.</summary>
        /// <param name="webContext">The web context wrapper.</param>
        public RequestLifeCycleHandler(IWebContext webContext, EventBroker broker, InstallationManager installer, IErrorHandler errors)
        {
            this.webContext = webContext;
            this.broker = broker;
            this.errors = errors;
            this.installer = installer;
        }

        public void Init(EventBroker broker)
        {
            Debug.WriteLine("RequestLifeCycleHandler.Init");

            broker.BeginRequest += Application_BeginRequest;
            broker.AuthorizeRequest += Application_AuthorizeRequest;
            broker.AcquireRequestState += Application_AcquireRequestState;
            broker.Error += Application_Error;
            broker.EndRequest += Application_EndRequest;
        }

        protected virtual void Application_BeginRequest(object sender, EventArgs e)
        {
            if (!initialized)
            {
                // we need to have reached begin request before we can do certain 
                // things in IIS7. concurrency isn't crucial here.
                initialized = true;
                if (webContext.IsWeb)
                {
                    if (Url.ServerUrl == null)
                        Url.ServerUrl = webContext.Url.HostUrl;
                    if (checkInstallation)
                        CheckInstallation();
                }
            }

        }

        private void CheckInstallation()
        {
          
            if (!installer.GetStatus().IsInstalled)
            {
                webContext.Response.Redirect(installerUrl);
            }
        }

        /// <summary>Infuses the http handler (usually an aspx page) with the content page associated with the url if it implements the <see cref="IContentTemplate"/> interface.</summary>
        protected virtual void Application_AcquireRequestState(object sender, EventArgs e)
        {
          
        }

        protected virtual void Application_AuthorizeRequest(object sender, EventArgs e)
        {
           
        }

        protected virtual void Application_Error(object sender, EventArgs e)
        {
            HttpApplication application = sender as HttpApplication;
            if (application != null)
            {
                Exception ex = application.Server.GetLastError();
                if (ex != null)
                {
                    errors.Notify(ex);
                }
            }
        }

        protected virtual void Application_EndRequest(object sender, EventArgs e)
        {
            webContext.Close();
        }

        #region IStartable Members

        public void Start()
        {
            broker.BeginRequest += Application_BeginRequest;
            broker.AuthorizeRequest += Application_AuthorizeRequest;
            broker.AcquireRequestState += Application_AcquireRequestState;
            broker.Error += Application_Error;
            broker.EndRequest += Application_EndRequest;
        }

        public void Stop()
        {
            broker.BeginRequest -= Application_BeginRequest;
            broker.AuthorizeRequest -= Application_AuthorizeRequest;
            broker.AcquireRequestState -= Application_AcquireRequestState;
            broker.Error -= Application_Error;
            broker.EndRequest -= Application_EndRequest;
        }

        #endregion

    }
}
